using ICSharpCode.TextEditor.Document;
using System;
using System.Collections.Generic;
using System.Drawing;
namespace ICSharpCode.TextEditor
{
	public class DrawableLine
	{
		private class SimpleTextWord
		{
			internal TextWordType Type;
			internal string Word;
			internal bool Bold;
			internal Color Color;
			internal static readonly DrawableLine.SimpleTextWord Space = new DrawableLine.SimpleTextWord(TextWordType.Space, " ", false, Color.Black);
			internal static readonly DrawableLine.SimpleTextWord Tab = new DrawableLine.SimpleTextWord(TextWordType.Tab, "\t", false, Color.Black);
			public SimpleTextWord(TextWordType Type, string Word, bool Bold, Color Color)
			{
				this.Type = Type;
				this.Word = Word;
				this.Bold = Bold;
				this.Color = Color;
			}
		}
		private static StringFormat sf = (StringFormat)StringFormat.GenericTypographic.Clone();
		private List<DrawableLine.SimpleTextWord> words = new List<DrawableLine.SimpleTextWord>();
		private SizeF spaceSize;
		private Font monospacedFont;
		private Font boldMonospacedFont;
		public int LineLength
		{
			get
			{
				int num = 0;
				foreach (DrawableLine.SimpleTextWord current in this.words)
				{
					num += current.Word.Length;
				}
				return num;
			}
		}
		public DrawableLine(IDocument document, LineSegment line, Font monospacedFont, Font boldMonospacedFont)
		{
			this.monospacedFont = monospacedFont;
			this.boldMonospacedFont = boldMonospacedFont;
			if (line.Words != null)
			{
				using (List<TextWord>.Enumerator enumerator = line.Words.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						TextWord current = enumerator.Current;
						if (current.Type == TextWordType.Space)
						{
							this.words.Add(DrawableLine.SimpleTextWord.Space);
						}
						else
						{
							if (current.Type == TextWordType.Tab)
							{
								this.words.Add(DrawableLine.SimpleTextWord.Tab);
							}
							else
							{
								this.words.Add(new DrawableLine.SimpleTextWord(TextWordType.Word, current.Word, current.Bold, current.Color));
							}
						}
					}
					return;
				}
			}
			this.words.Add(new DrawableLine.SimpleTextWord(TextWordType.Word, document.GetText(line), false, Color.Black));
		}
		public void SetBold(int startIndex, int endIndex, bool bold)
		{
			if (startIndex < 0)
			{
				throw new ArgumentException("startIndex must be >= 0");
			}
			if (startIndex > endIndex)
			{
				throw new ArgumentException("startIndex must be <= endIndex");
			}
			if (startIndex == endIndex)
			{
				return;
			}
			int num = 0;
			for (int i = 0; i < this.words.Count; i++)
			{
				DrawableLine.SimpleTextWord simpleTextWord = this.words[i];
				if (num >= endIndex)
				{
					return;
				}
				int num2 = num + simpleTextWord.Word.Length;
				if (startIndex <= num && endIndex >= num2)
				{
					simpleTextWord.Bold = bold;
				}
				else
				{
					if (startIndex <= num)
					{
						int num3 = endIndex - num;
						DrawableLine.SimpleTextWord item = new DrawableLine.SimpleTextWord(simpleTextWord.Type, simpleTextWord.Word.Substring(num3), simpleTextWord.Bold, simpleTextWord.Color);
						this.words.Insert(i + 1, item);
						simpleTextWord.Bold = bold;
						simpleTextWord.Word = simpleTextWord.Word.Substring(0, num3);
					}
					else
					{
						if (startIndex < num2)
						{
							int num4 = startIndex - num;
							DrawableLine.SimpleTextWord item2 = new DrawableLine.SimpleTextWord(simpleTextWord.Type, simpleTextWord.Word.Substring(num4), simpleTextWord.Bold, simpleTextWord.Color);
							this.words.Insert(i + 1, item2);
							simpleTextWord.Word = simpleTextWord.Word.Substring(0, num4);
						}
					}
				}
				num = num2;
			}
		}
		public static float DrawDocumentWord(Graphics g, string word, PointF position, Font font, Color foreColor)
		{
			if (word == null || word.Length == 0)
			{
				return 0f;
			}
			SizeF sizeF = g.MeasureString(word, font, 32768, DrawableLine.sf);
			g.DrawString(word, font, BrushRegistry.GetBrush(foreColor), position, DrawableLine.sf);
			return sizeF.Width;
		}
		public SizeF GetSpaceSize(Graphics g)
		{
			if (this.spaceSize.IsEmpty)
			{
				this.spaceSize = g.MeasureString("-", this.boldMonospacedFont, new PointF(0f, 0f), DrawableLine.sf);
			}
			return this.spaceSize;
		}
		public void DrawLine(Graphics g, ref float xPos, float xOffset, float yPos, Color c)
		{
			SizeF sizeF = this.GetSpaceSize(g);
			foreach (DrawableLine.SimpleTextWord current in this.words)
			{
				switch (current.Type)
				{
					case TextWordType.Word:
					{
						xPos += DrawableLine.DrawDocumentWord(g, current.Word, new PointF(xPos + xOffset, yPos), current.Bold ? this.boldMonospacedFont : this.monospacedFont, (c == Color.Empty) ? current.Color : c);
						break;
					}
					case TextWordType.Space:
					{
						xPos += sizeF.Width;
						break;
					}
					case TextWordType.Tab:
					{
						float num = sizeF.Width * 4f;
						xPos += num;
						xPos = (float)((int)((xPos + 2f) / num)) * num;
						break;
					}
				}
			}
		}
		public void DrawLine(Graphics g, ref float xPos, float xOffset, float yPos)
		{
			this.DrawLine(g, ref xPos, xOffset, yPos, Color.Empty);
		}
		public float MeasureWidth(Graphics g, float xPos)
		{
			SizeF sizeF = this.GetSpaceSize(g);
			foreach (DrawableLine.SimpleTextWord current in this.words)
			{
				switch (current.Type)
				{
					case TextWordType.Word:
					{
						if (current.Word != null && current.Word.Length > 0)
						{
							xPos += g.MeasureString(current.Word, current.Bold ? this.boldMonospacedFont : this.monospacedFont, 32768, DrawableLine.sf).Width;
						}
						break;
					}
					case TextWordType.Space:
					{
						xPos += sizeF.Width;
						break;
					}
					case TextWordType.Tab:
					{
						float num = sizeF.Width * 4f;
						xPos += num;
						xPos = (float)((int)((xPos + 2f) / num)) * num;
						break;
					}
				}
			}
			return xPos;
		}
	}
}
